package com.zhiyin.seal.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiyin.seal.entity.bo.ApplyBo;
import com.zhiyin.seal.entity.bo.StampRecordBo;
import com.zhiyin.seal.entity.bo.StampSearchParamsBo;
import com.zhiyin.seal.entity.dto.ResponseDTO;
import com.zhiyin.seal.entity.dto.StatisticsParamsDTO;
import com.zhiyin.seal.entity.vo.StatisticsRankingVo;
import com.zhiyin.seal.entity.vo.StatisticsVo;
import com.zhiyin.seal.service.ApplyService;
import com.zhiyin.seal.service.CompanyService;
import com.zhiyin.seal.service.StampService;
import com.zhiyin.seal.util.DateUtil;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 统计业务控制器
 */
@RestController
@RequestMapping("/statistics")
public class StatisticsController {

    @Autowired
    ApplyService applyService;

    @Autowired
    StampService stampService;

    @Autowired
    CompanyService companyService;

    @PostMapping("/calculate")
    public ResponseDTO<StatisticsVo> getStatisticsData(@RequestBody StatisticsParamsDTO statisticsParamsDTO){
        // 实例化返回实体对象
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setTotal(0);
        // 赋值查询参数
        StampSearchParamsBo stampSearchParamsBo = new StampSearchParamsBo();
        stampSearchParamsBo.setCompanyId(statisticsParamsDTO.getCompanyId());
        stampSearchParamsBo.setStartTime(statisticsParamsDTO.getStartTime());
        stampSearchParamsBo.setEndTime(statisticsParamsDTO.getEndTime());
        stampSearchParamsBo.setHasAdmin(true);
        stampSearchParamsBo.setPaging(false);
        // 根据查询类型赋值不同的查询条件
        if(statisticsParamsDTO.getType() != null){
            String type = statisticsParamsDTO.getType();
            if(type.equals("contract")){
                stampSearchParamsBo.setFileType(statisticsParamsDTO.getValue());
            } else if(type.equals("user")){
                stampSearchParamsBo.setStampUserId(Long.parseLong(statisticsParamsDTO.getValue()));
            } else {
                stampSearchParamsBo.setSealId(Long.parseLong(statisticsParamsDTO.getValue()));
            }
        }
        // 查询盖章记录
        List<StampRecordBo> stampRecordBoList = stampService.getRecordList(stampSearchParamsBo);
        if(stampRecordBoList.size() > 0){
            int total = 0;
            int approvalCount = 0;
            int noneApprovalCount = 0;
            // 计算审批和无审批用印次数
            for (StampRecordBo stampRecordBo : stampRecordBoList) {
                int stampCount = stampRecordBo.getStampCount();
                total += stampCount;
                // 无审批
                if(stampRecordBo.getApplyId().equals(0l)){
                    noneApprovalCount+=stampCount;
                } else {
                    approvalCount+=stampCount;
                }
            }
            // 赋值总次数
            statisticsVo.setTotal(total);
            // 赋值审批用印次数
            statisticsVo.setApprovalCount(approvalCount);
            // 赋值无审批用印次数
            statisticsVo.setNoneApprovalCount(noneApprovalCount);
            // 加载关联单据，并赋值
            List<ApplyBo> applyBoList = applyService.getStampRecordApplyList(stampSearchParamsBo);
            if(applyBoList != null){
                Map<Long,ApplyBo> applyBoMap = Maps.newHashMap();
                for (ApplyBo applyBo : applyBoList) {
                    applyBoMap.put(applyBo.getId(),applyBo);
                }
                for (StampRecordBo stampRecordBo : stampRecordBoList) {
                    stampRecordBo.setApplyInfo(applyBoMap.get(stampRecordBo.getApplyId()));
                }
            }
            // 判断计算维度,month:月度,year:年度
            Map<Integer,Integer> lineChartData = Maps.newHashMap();
            if(statisticsParamsDTO.getDimension().equals("month")){
                try {
                    Date startDate = DateUtil.COMMON_DATE_FORMATE.parse(stampSearchParamsBo.getStartTime());
                    int days = DateUtil.getDaysOfMonth(startDate);
                    for(int i=1;i<=days;i++){
                        lineChartData.put(i,0);
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            } else {
                int month = 12;
                for(int i=1;i<=month;i++){
                    lineChartData.put(i,0);
                }
            }
            // 计算盖章走势
            CaculateLineChartData(stampRecordBoList,statisticsParamsDTO.getDimension(),lineChartData);
            List<Integer> lineChartCategories = new ArrayList<>(lineChartData.keySet());
            List<Integer> lineChartSeries = new ArrayList<>(lineChartData.values());
            statisticsVo.setLineChartCategories(lineChartCategories);
            statisticsVo.setLineChartSeries(lineChartSeries);
            // 计算排行榜
            statisticsVo.setRankingList(CaculateRankingList(stampRecordBoList));
        }

        return ResponseDTO.succData(statisticsVo);
    }

    @PostMapping("/report")
    public void getReport(@RequestBody StatisticsParamsDTO statisticsParamsDTO, HttpServletResponse response){
        StatisticsVo statisticsVo = getStatisticsData(statisticsParamsDTO).getData();
        try {
            String dimension = statisticsParamsDTO.getDimension();
            String excelPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            String reportTitle = "";
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(DateUtil.COMMON_DATE_FORMATE.parse(statisticsParamsDTO.getStartTime()));
            if(dimension.equals("year")){
                excelPath +="year_stamp_report.xls";
                reportTitle = calendar.get(Calendar.YEAR) + "年盖章报表";
            } else {
                excelPath +="month_stamp_report.xls";
                reportTitle = calendar.get(Calendar.YEAR) + "年" + (calendar.get(Calendar.MONTH) + 1) +"月盖章报表";
            }
            if(statisticsParamsDTO.getType() != null){
                String type = statisticsParamsDTO.getType();
                if(type.equals("contract")){
                    reportTitle +="(合同维度)";
                } else if(type.equals("user")){
                    reportTitle +="(人员维度)";
                } else {
                    reportTitle +="(印章维度)";
                }
            }
            // 读取模板
            HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(excelPath));
            // 读取第一张表单
            HSSFSheet sheet1 = wb.getSheetAt(0);
            // 重新设置标题
            HSSFRow row = sheet1.getRow(0);
            HSSFCell cell = row.getCell(0);
            cell.setCellValue(reportTitle);
            // 设置审批用印次数
            if(statisticsVo.getApprovalCount() != null){
                row = sheet1.getRow(3);
                cell = row.getCell(2);
                cell.setCellValue(statisticsVo.getApprovalCount());
            }
            // 设置无审批用印次数
            if(statisticsVo.getNoneApprovalCount() != null){
                row = sheet1.getRow(4);
                cell = row.getCell(2);
                cell.setCellValue(statisticsVo.getNoneApprovalCount());
            }
            // 设置合计用印次数
            if(statisticsVo.getTotal() != null){
                row = sheet1.getRow(5);
                cell = row.getCell(2);
                cell.setCellValue(statisticsVo.getTotal());
            }
            // 设置走势图数据
            if(statisticsVo.getLineChartSeries() != null){
                List<Integer> lineChartSeries = statisticsVo.getLineChartSeries();
                for (int i = 0; i < lineChartSeries.size(); i++) {
                    sheet1.getRow(i+8).getCell(1).setCellValue(lineChartSeries.get(i));
                }
            }
            // 排行榜
            if(statisticsVo.getRankingList() != null){
                List<StatisticsRankingVo> rankingList = statisticsVo.getRankingList();
                // 合同
                HSSFSheet sheet2 = wb.getSheetAt(1);
                sheet2.getRow(0).getCell(0).setCellValue(reportTitle);
                int index = 1;
                for (StatisticsRankingVo statisticsRankingVo : rankingList) {
                    if(statisticsRankingVo.getType().equals("contract")){
                        row = sheet2.createRow(index + 2);
                        row.createCell(0).setCellValue(index);
                        row.createCell(1).setCellValue(statisticsRankingVo.getName());
                        row.createCell(2).setCellValue(statisticsRankingVo.getStampCount());
                        index += 1;
                    }
                }
                // 人员
                HSSFSheet sheet3 = wb.getSheetAt(2);
                sheet3.getRow(0).getCell(0).setCellValue(reportTitle);
                index = 1;
                for (StatisticsRankingVo statisticsRankingVo : rankingList) {
                    if(statisticsRankingVo.getType().equals("user")){
                        row = sheet3.createRow(index + 2);
                        row.createCell(0).setCellValue(index);
                        row.createCell(1).setCellValue(statisticsRankingVo.getName());
                        row.createCell(2).setCellValue(statisticsRankingVo.getStampCount());
                        index += 1;
                    }
                }
                // 印章
                HSSFSheet sheet4 = wb.getSheetAt(3);
                sheet4.getRow(0).getCell(0).setCellValue(reportTitle);
                index = 1;
                for (StatisticsRankingVo statisticsRankingVo : rankingList) {
                    if(statisticsRankingVo.getType().equals("seal")){
                        row = sheet4.createRow(index + 2);
                        row.createCell(0).setCellValue(index);
                        row.createCell(1).setCellValue(statisticsRankingVo.getName());
                        row.createCell(2).setCellValue(statisticsRankingVo.getStampCount());
                        index += 1;
                    }
                }
            }
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode("stamp_report.xls", "UTF-8"));
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void CaculateLineChartData(List<StampRecordBo> stampRecordBoList,String dimension,Map<Integer,Integer> lineChartData){
        for (StampRecordBo stampRecordBo : stampRecordBoList) {
            int key = 0;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(stampRecordBo.getCreateTime());
            if(dimension.equals("month")){
                key = calendar.get(Calendar.DAY_OF_MONTH);
            } else {
                key = calendar.get(Calendar.MONTH) + 1;
            }
            int stampCount = lineChartData.get(key);
            stampCount +=stampRecordBo.getStampCount();
            lineChartData.put(key,stampCount);
        }
    }

    private List<StatisticsRankingVo> CaculateRankingList(List<StampRecordBo> stampRecordBoList){
        // 合同排行榜
        Map<String,StatisticsRankingVo> contractRankingMap = Maps.newHashMap();
        // 人员排行榜
        Map<Long,StatisticsRankingVo> userRankingMap = Maps.newHashMap();
        // 印章排行榜
        Map<Long,StatisticsRankingVo> sealRankingMap = Maps.newHashMap();
        for (StampRecordBo stampRecordBo : stampRecordBoList) {
            StatisticsRankingVo statisticsRankingVo;
            ApplyBo applyBo = stampRecordBo.getApplyInfo();
            // 组装合同排行榜
            if(applyBo != null){
                String fileType = applyBo.getFileType();
                statisticsRankingVo = contractRankingMap.get(fileType);
                if(statisticsRankingVo == null){
                    statisticsRankingVo = new StatisticsRankingVo();
                    statisticsRankingVo.setId(0l);
                    statisticsRankingVo.setImgUrl("../../../images/workbench/contract_type.png");
                    statisticsRankingVo.setName(fileType);
                    statisticsRankingVo.setType("contract");
                    statisticsRankingVo.setStampCount(0);
                }
                statisticsRankingVo.setStampCount(statisticsRankingVo.getStampCount() + stampRecordBo.getStampCount());
                contractRankingMap.put(fileType,statisticsRankingVo);
            }
            // 组装人员排行榜
            Long stampUserId = stampRecordBo.getStampUser().getId();
            statisticsRankingVo = userRankingMap.get(stampUserId);
            if(statisticsRankingVo == null){
                statisticsRankingVo = new StatisticsRankingVo();
                statisticsRankingVo.setId(stampUserId);
                statisticsRankingVo.setImgUrl(stampRecordBo.getStampUser().getAvatarUrl());
                statisticsRankingVo.setName(stampRecordBo.getStampUser().getNickName());
                statisticsRankingVo.setType("user");
                statisticsRankingVo.setStampCount(0);
            }
            statisticsRankingVo.setStampCount(statisticsRankingVo.getStampCount() + stampRecordBo.getStampCount());
            userRankingMap.put(stampUserId,statisticsRankingVo);
            // 组装印章排行榜
            Long sealId = stampRecordBo.getSealInfo().getId();
            statisticsRankingVo = sealRankingMap.get(sealId);
            if(statisticsRankingVo == null){
                statisticsRankingVo = new StatisticsRankingVo();
                statisticsRankingVo.setId(sealId);
                statisticsRankingVo.setImgUrl("../../../images/workbench/seal.png");
                statisticsRankingVo.setName(stampRecordBo.getSealInfo().getName());
                statisticsRankingVo.setType("seal");
                statisticsRankingVo.setStampCount(0);
            }
            statisticsRankingVo.setStampCount(statisticsRankingVo.getStampCount() + stampRecordBo.getStampCount());
            sealRankingMap.put(sealId,statisticsRankingVo);
        }

        List<StatisticsRankingVo> contractRankingList = new ArrayList(contractRankingMap.values());
        contractRankingList = contractRankingList.stream().sorted(Comparator.comparing(StatisticsRankingVo::getStampCount).reversed()).collect(Collectors.toList());

        List<StatisticsRankingVo> userRankingList = new ArrayList(userRankingMap.values());
        userRankingList = userRankingList.stream().sorted(Comparator.comparing(StatisticsRankingVo::getStampCount).reversed()).collect(Collectors.toList());

        List<StatisticsRankingVo> sealRankingList = new ArrayList(sealRankingMap.values());
        sealRankingList = sealRankingList.stream().sorted(Comparator.comparing(StatisticsRankingVo::getStampCount).reversed()).collect(Collectors.toList());

        List<StatisticsRankingVo> rankingVoList = Lists.newArrayList();
        rankingVoList.addAll(contractRankingList);
        rankingVoList.addAll(userRankingList);
        rankingVoList.addAll(sealRankingList);

        return rankingVoList;
    }
}
